package com.xyyl.patient.controller;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xyyl.patient.common.dypls.AliyunDyplsService;
import com.xyyl.patient.common.easemob.EasemobApiService;
import com.xyyl.patient.common.utils.SysConfigUtils;
import com.xyyl.patient.core.constant.AppEnum;
import com.xyyl.patient.core.controller.BaseController;
import com.xyyl.patient.core.util.DateUtils;
import com.xyyl.patient.core.util.ResponseBodyResult;
import com.xyyl.patient.core.util.StringUtils;
import com.xyyl.patient.entity.base.BindAxbEntity;
import com.xyyl.patient.entity.order.PhoneOrder;
import com.xyyl.patient.entity.order.SpeedPhoneOrder;
import com.xyyl.patient.entity.user.User;
import com.xyyl.patient.service.base.BindAxbService;
import com.xyyl.patient.service.doctor.DoctorService;
import com.xyyl.patient.service.order.PhoneOrderService;
import com.xyyl.patient.service.order.SpeedPhoneOrderService;
import com.xyyl.patient.service.user.UserService;
import com.xyyl.patient.vo.user.UserVo;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.api.impl.WxMpQrcodeServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpUserServiceImpl;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author chens
 * @projectName:xyyl-patient-web
 * @ClassName: HomepageController
 * @Description: 应用首页
 * 1.授权获取用户基本信息，并绑定存储；
 * 2.注册环信IM账号
 * @date 2017年8月21日
 */
@Controller
@RequestMapping("/homepage")
public class HomepageController extends BaseController {

    private Logger logger = LogManager.getLogger(HomepageController.class);
    @Autowired
    private UserService userService;

    @Autowired
    private BindAxbService bindAxbService;

    @Autowired
    private SpeedPhoneOrderService speedPhoneOrderService;

    @Autowired
    private PhoneOrderService phoneOrderService;

    @Autowired
    private DoctorService doctorService;
    protected WxMpService wxMpService = new WxMpServiceImpl();

    protected WxMpUserService wxMpUserService = new WxMpUserServiceImpl(wxMpService);


    protected WxMpQrcodeService wxMpQrcodeService = new WxMpQrcodeServiceImpl(wxMpService);

    /**
     * appid
     **/
    @Value("#{weixin['common.appid']}")
    private String appid;

    /**
     * appSecrect
     **/
    @Value("#{weixin['common.appSecrect']}")
    private String appSecrect;

    /**
     * 默认静默授权
     **/
    private String scope = "snsapi_base";
    @Value("#{weixin['oauth.state']}")
    private String state = "989";

    /**
     * 静默授权重定向配置url
     **/
    @Value("#{weixin['oauth.openid_redirect_uri']}")
    private String openid_redirect_uri;

    /**
     * 网页授权重定向url
     **/
    @Value("#{weixin['oauth.base_redirect_uri']}")
    private String base_redirect_uri;

    /**
     * 环信账号前缀
     **/
    @Value("#{easemob['user_prefix']}")
    private String user_prefix;

    /**
     * 环信账号默认密码
     **/
    @Value("#{easemob['default_passwd']}")
    private String default_passwd;

    /**
     * 域名
     **/
    @Value("#{weixin['common.domain']}")
    private String domain;

    /**
     * 授权成功，返回页面
     **/
    @Value("#{weixin['oauth.return_uri']}")
    private String return_url;

    @Value("#{weixin['common.web.domain']}")
    private String webDomain;

    /**
     * @param @return 参数
     * @return WxMpInMemoryConfigStorage    返回类型
     * @throws
     * @Title: initConfig
     * @Description: 初始化配置信息
     */
    private WxMpInMemoryConfigStorage initConfig() {
        WxMpInMemoryConfigStorage configStorage = new WxMpInMemoryConfigStorage();
        configStorage.setAppId(appid);
        configStorage.setSecret(appSecrect);
        return configStorage;
    }

    /**
     * @param @param  scopeType
     * @param @return
     * @param @throws UnsupportedEncodingException    参数
     * @return String    返回类型
     * @throws
     * @Title: getOpenid
     * @Description: 获取openid
     * 流程： 1.进入应用首页，判断localstore中openid和userid是否为空，若为空则从服务器获取用户的基本信息,获取成功后，
     * 重定向到指定html页面； 2.进入用户中心，获取用户资料信息,通过oauth获取用户资料 @param @return 参数
     * scopeType: 1,静默授权，2.普通授权(获取用户信息)
     */
    @RequestMapping(value = "/oauth", method = RequestMethod.GET)
    public String getOpenid(String scopeType, String redirect_uri) throws UnsupportedEncodingException {
        if (StringUtils.isNotEmpty(redirect_uri)) {
            return_url = webDomain + redirect_uri;
        }
        logger.info("生成授权重定向地址:{}", return_url);
        return initAuthInfo(scopeType);
    }

    private String initAuthInfo(String scopeType) throws UnsupportedEncodingException {

        String redirect_uri = openid_redirect_uri;
        if (!StringUtils.isEmpty(scopeType) && "1".equals(scopeType)) {
            scope = "snsapi_userinfo";
            redirect_uri = domain + base_redirect_uri;
        }

        /** 參數配置 **/
        wxMpService.setWxMpConfigStorage(initConfig());
        String requestUrl = wxMpService.oauth2buildAuthorizationUrl(redirect_uri, scope, state);

        return "redirect:" + requestUrl;/** 重定向微信授权界面 **/
    }

    /**
     * @param @param  code
     * @param @param  redirectAttributes
     * @param @return 参数
     * @return String    返回类型
     * @throws
     * @Title: getUserInfo
     * @Description: 获取用户的基本信息，跳转网页授权
     */
    @RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
    public String getUserInfo(String code, RedirectAttributes redirectAttributes) {

        logger.info("授权code：{0}", code);
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = null;
        WxMpUser wxMpUser = null;
        Integer userid = null;
        try {

            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);

            if (wxMpOAuth2AccessToken != null) {

                //获取用户基本信息，是否关注该服务号
                WxMpUser userInfo = wxMpUserService.userInfo(wxMpOAuth2AccessToken.getOpenId());

                //获取用户的明细
                wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
                wxMpUser.setSubscribe(userInfo.getSubscribe());

                userid = bindUserInfo(wxMpUser);
            }

        } catch (WxErrorException e) {
            logger.error("获取token失败：{}", e);
            return null;
        }
        redirectAttributes.addAttribute("userid", userid)
                .addAttribute("openid", wxMpUser.getOpenId())
                .addAttribute("nickName", wxMpUser.getNickname())
                .addAttribute("subscribe", wxMpUser.getSubscribe());
        logger.debug("授权成功，重定向地址：{}", return_url);
        return "redirect:" + return_url;
    }

    /**
     * @param @param  code
     * @param @param  redirectAttributes
     * @param @return 参数
     * @return String    返回类型
     * @throws
     * @Title: getUserOpenid
     * @Description: 获取用户openid, 静默授权
     */
    @RequestMapping(value = "/getUserOpenid", method = RequestMethod.GET)
    public String getUserOpenid(String code, RedirectAttributes redirectAttributes) {

        logger.info("授权code：{0}", code);
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = null;
        try {

            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);

            WxMpUser wxMpUser = new WxMpUser();
            wxMpUser.setOpenId(wxMpOAuth2AccessToken.getOpenId());
            bindUserInfo(wxMpUser);
        } catch (WxErrorException e) {
            logger.error("获取token失败：{}", e);
            return null;
        }
        redirectAttributes.addAttribute("openid", wxMpOAuth2AccessToken.getOpenId());
        return "redirect:" + return_url;
    }

    /**
     * @param @param  wxMpUser
     * @param @return 参数
     * @return Integer    返回类型
     * @throws
     * @Title: bindUserInfo
     * @Description: 绑定用户基本信息
     */
    private Integer bindUserInfo(WxMpUser wxMpUser) {

        User user = new User();
        try {
            String nickName = URLEncoder.encode(wxMpUser.getNickname(), "UTF-8");
            user.setNickname(nickName);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        user.setAvatar(wxMpUser.getHeadImgUrl());
        if (!StringUtils.isEmpty(wxMpUser.getSex())) {
            user.setSex("男".equals(wxMpUser.getSex()) ? 1 : 2);
        } else {
            user.setSex(0);
        }
        user.setCityname(wxMpUser.getProvince() != null ? wxMpUser.getProvince() + " " + wxMpUser.getCity() : null);
        user.setAreaname(wxMpUser.getCountry());
        user.setOpenid(wxMpUser.getOpenId());

        Integer id = userService.bindUserInfo(user);

        /** 綁定环信账号 **/
        bindEasemobUserInfo(user);
        return id;

    }

    /**
     * @param @param user    参数
     * @return void    返回类型
     * @throws
     * @Title: bindEasemobUserInfo
     * @Description:绑定环信账号，并更新
     */
    private void bindEasemobUserInfo(User user) {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                UserVo userVo = userService.queryUserDetailById(user.getId());
                if (userVo != null && StringUtils.isEmpty(userVo.getUsernameim())) {
                    String code = EasemobApiService.register(user.getOpenid(), default_passwd);
                    if (StringUtils.isNotEmpty(code)) {
                        user.setUsernameim(code);
                        userService.bindUserInfo(user);
                    }
                }
            }
        });
    }

    /**
     * @param @param  url
     * @param @return 参数
     * @return JSONObject    返回类型
     * @throws
     * @Title: getJsApiSign
     * @Description:getJsApiSign
     */
    @RequestMapping(value = "/getJsApiSign", method = RequestMethod.GET)
    @ResponseBody
    public JSONObject getJsApiSign(@RequestParam String url) {

        WxJsapiSignature jsapiSignature = null;
        logger.info("参数url:{}", url);
        try {

            /** 參數配置 **/
            wxMpService.setWxMpConfigStorage(initConfig());
            jsapiSignature = wxMpService.createJsapiSignature(webDomain + url);

            return ResponseBodyResult.success("apiSign获取成功", jsapiSignature);
        } catch (Exception e) {
            return ResponseBodyResult.error("apiSign获取失败", e);
        }
    }

    /**
     * @param @param  openid
     * @param @return 参数
     * @return JSONObject    返回类型
     * @throws
     * @Title: restEasemobIm
     * @Description: 针对已有的环信账号进行重置
     */
    @RequestMapping(value = "/restEasemobIm", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject restEasemobIm(@RequestParam String openid) {

        logger.info("openid:{}", openid);
        try {
            String code = EasemobApiService.register(openid, default_passwd);
            if (StringUtils.isNotEmpty(code)) {
                User user = new User();
                user.setUsernameim(code);
                user.setOpenid(openid);
                userService.bindUserInfo(user);
                return ResponseBodyResult.success("环信账号注册成功", code);
            } else {
                return ResponseBodyResult.success("环信账号不能重复注册", -1);
            }

        } catch (Exception e) {
            return ResponseBodyResult.error("环信账号重置失败", e);
        }
    }


    /**
     * 为医生生成唯一的推广码
     * @param doctorId
     * @return
     */
	/*@RequestMapping(value = "/qrCodeCreateTmpTicket", method = RequestMethod.POST)
	@ResponseBody
	public JSONObject qrCodeCreateTmpTicket(@RequestParam Integer doctorId) {

		logger.info("openid:{}", doctorId);
		try {
			
			wxMpService.setWxMpConfigStorage(initConfig());
			
			WxMpQrcodeService mpQrcodeService=new WxMpQrcodeServiceImpl(wxMpService);
			WxMpQrCodeTicket wxCodeTicket = mpQrcodeService.qrCodeCreateTmpTicket(doctorId, 2592000);
			
			//生成医生推广码
			File file=wxMpService.getQrcodeService().qrCodePicture(wxCodeTicket);
			InputStream inputStream=new FileInputStream(file);
			
			//上传阿里云
			FileUploadRecord fileUploadRecord=AliyunCloudStorageService.upload(inputStream,UUID.randomUUID()+".jpg");
			return ResponseBodyResult.success("推广码已生成："+fileUploadRecord.getFullurl());
			
		} catch (Exception e) {
			return ResponseBodyResult.error("推广码生成失败", e);
		}
	}*/

    /**
     * 为医生生与患者绑定虚拟中间号
     *
     * @param typeId,id
     * @return JSONObject
     */
    @RequestMapping(value = "/callAxBApi", method = RequestMethod.GET)
    @ResponseBody
    public JSONObject callAxBApi(Integer typeId, Integer id) {
        String doctorPhone = "";
        String patientPhone = "";
        Integer doctorId = null;
        String secretNo = "";
//        String now = DateUtils.addMinute(new Date(System.currentTimeMillis()), Integer.parseInt(SysConfigUtils
//                .getConfigValue(AppEnum.sysConfig.ORDER_AUTO_NOTICE_TIME.name())));
        //取出订单 需要拨打的患者手机号
        if (typeId == 3) {
            PhoneOrder phoneOrder = phoneOrderService.queryOrderDetailById(id);
            if (phoneOrder != null) {
                patientPhone = phoneOrder.getAnswerPhone();
                doctorId = phoneOrder.getDoctorid();
//                if (DateUtils.toTimeMillis(now) <= DateUtils.toTimeMillis(phoneOrder.getServiceTime()+":00")) {
//                    Map<String, Object> paramMap1 = Maps.newHashMap();
//                    paramMap1.put("secretNo", 1);
//                    return ResponseBodyResult.success("未到预约时间，您只能提前" + SysConfigUtils
//                            .getConfigValue(AppEnum.sysConfig.ORDER_AUTO_NOTICE_TIME.name()) + "分钟给患者回电",paramMap1);
//                }
            }
        } else if (typeId == 4) {
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("id", id);
            SpeedPhoneOrder speedPhoneOrder = speedPhoneOrderService.queryObject(paramMap);
            if (speedPhoneOrder != null) {
                patientPhone = speedPhoneOrder.getAnswerMobile();
                doctorId = speedPhoneOrder.getDoctorId();
            }
        }
        //取出医生的手机号
        if (doctorId != 0 && !patientPhone.isEmpty()) {
            doctorPhone = doctorService.queryDoctorMoblieById(doctorId);
        }
        if (!doctorPhone.isEmpty()) {
            List<BindAxbEntity> bindAxbEntityList = bindAxbService.selectAxbList(doctorPhone);
            //如果有绑定 更新绑定
            if (bindAxbEntityList != null && !bindAxbEntityList.isEmpty()) {
                BindAxbEntity bindAxbEntity = bindAxbEntityList.get(0);
                //解绑原来,患者, 更新 新的患者绑定
                secretNo = bindAxbEntity.getSecretPhone();
                if (bindAxbEntity.getBPhone().equals(patientPhone)) {

                } else {
                    //根据绑定主键SubsId , 中间号SecretPhone ,和新号码,跟新新的绑定
                    AliyunDyplsService.updateSubscription(bindAxbEntity.getSubsId(), bindAxbEntity.getSecretPhone(), patientPhone);
                }
            } else {
                // 没有绑定 新增绑定
                secretNo = AliyunDyplsService.BindAxb(doctorPhone, patientPhone);
            }
        }
        if (secretNo.length()==0|secretNo.isEmpty() |secretNo.substring(0,3).equals("isv")| secretNo.length() != 11) {
            return ResponseBodyResult.success("虚拟手机号绑定失败", secretNo);
        } else {
            Map<String, Object> paramMap1 = Maps.newHashMap();
            paramMap1.put("secretNo", secretNo);
            return ResponseBodyResult.success("虚拟手机号绑定成功", paramMap1);
        }

    }

    private ExecutorService executorService = Executors.newSingleThreadExecutor();
}
